#include "head.h"

//FBOThread::FBOThread(QObject *parent, MyOpenGLRender *render)
//    :QThread(parent)
//    ,_render(render)
//{
//    _secondContext->setShareContext(render->_firstContext);
//    _secondContext->create();
//    _secondContext->moveToThread(this);

//    start();
//}

//FBOThread::~FBOThread()
//{

//}

//void FBOThread::PushElement(H264Frame *ele)
//{
//    _list.push_back(ele);
//}

//void FBOThread::run()
//{

//    _render->initFBO();

//    while (1) {
//        while (_list.isEmpty()) {
//            std::this_thread::sleep_for(std::chrono::milliseconds(10));
//        }
//        auto ele = _list.takeFirst();
//        _render->renderContent(ele);
//    }
//}



//void FBORender::resizeGL(int w, int h)
//{
//    glViewport(0,0,w,h);
//}

//void FBORender::initializeGL()
//{

//}

//void FBORender::paintGL()
//{

//}

//void FBORender::Render(H264Frame *content)
//{
//    _render->renderContent(content);
//}




MyOpenGLRender::MyOpenGLRender(QWidget *parent)
    :QOpenGLWidget(parent)
{

}

MyOpenGLRender::~MyOpenGLRender()
{
    for(const auto &ele:_texture)
    {
        glDeleteTextures(1, &ele.second);
    }
//    glDeleteTextures(1, &_fboTexture);
//    glDeleteFramebuffers(1, &_fbo);
//    glDeleteRenderbuffers(1, &_fboRender);

//    glDeleteBuffers(6, _pboArry);
//    glDeleteBuffers(1, &_pbo);
//    glDeleteBuffers(1, &_pbo2);
    glDeleteBuffers(1, &_vbo);
    errPrint("~MyOpenGLRender");

}


void MyOpenGLRender::errPrint(const QString &information)
{
    decltype(glGetError()) err;
    err = glGetError();
    while (err != GL_NO_ERROR)
    {
        // auto string = gluErrorUnicodeStringEXT(GL_OUT_OF_MEMORY);
        // size_t lenU8 = WideCharToMultiByte(CP_ACP, 0, string, -1, nullptr, 0, nullptr, nullptr);
        // std::unique_ptr<char> u8str(new char[lenU8]());
        // WideCharToMultiByte(CP_ACP, 0, string, -1, u8str.get(), lenU8, nullptr, nullptr);
        qDebug()
            << "exit err! arr is " << err << information;
        err = glGetError();
    }
}

void MyOpenGLRender::initShaderProgrem()
{
    auto vertx = new QOpenGLShader(QOpenGLShader::Vertex, this);
    auto frag = new QOpenGLShader(QOpenGLShader::Fragment, this);

   auto flag = vertx->compileSourceFile(":/images/images/vertex.vert");
   if(!flag)
   {
       qDebug() << "vertex compile err!";
       exit(-1);
   }

   flag = frag->compileSourceFile(":/images/images/fragment.frag");
   if(!flag)
   {
       qDebug() << "frag compile err!";
       exit(-1);
   }

   _shaderprogram.addShader(vertx);
   _shaderprogram.addShader(frag);

   flag = _shaderprogram.link();
   if(!flag)
   {
       qDebug() << "link compile err!";
       exit(-1);
   }
   if(vertx != nullptr)
   {
       delete vertx;
       vertx = nullptr;
   }

   if(frag != nullptr)
   {
       delete frag;
       frag = nullptr;
   }
   errPrint("initShaderProgrem 80");
}


void MyOpenGLRender::initFBO()
{
    glGenTextures(1, &_fboTexture);
//    glActiveTexture(GL_TEXTURE3);
    glBindTexture( GL_TEXTURE_2D, _fboTexture);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);

    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width(), height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
    glBindTexture( GL_TEXTURE_2D, 0);


    glGenRenderbuffers(1, &_fboRender);
    glBindRenderbuffer(GL_RENDERBUFFER, _fboRender);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width(), height());
    glBindRenderbuffer(GL_RENDERBUFFER, 0);

    glGenFramebuffers(1, &_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,  GL_TEXTURE_2D, _fboTexture, 0);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _fboRender);

    auto statueFBO = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if(statueFBO == GL_FRAMEBUFFER_UNSUPPORTED_EXT)
    {
        qDebug() << "GL_FRAMEBUFFER_UNSUPPORTED_EXT";
        exit(0);
    }

    errPrint("initFBO");

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void MyOpenGLRender::initPBO()
{
//    glGenBuffers(6, _pboArry);
//    for(auto &ele:_pboArry)
//    {
//        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, ele);
//        glBufferData(GL_PIXEL_UNPACK_BUFFER, width() * height(), nullptr, GL_DYNAMIC_DRAW);//要用GL_DYNAMIC_DRAW
//        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
//    }


    glGenBuffers(2, _pboArry);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pboArry[0]);
    glBufferData(GL_PIXEL_UNPACK_BUFFER, width()*height()*2, nullptr, GL_DYNAMIC_DRAW);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _pboArry[1]);
    glBufferData(GL_PIXEL_UNPACK_BUFFER, width()*height()*2, nullptr, GL_DYNAMIC_DRAW);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    errPrint("initPBO 128");

}

void MyOpenGLRender::initTexture()
{
    _texture["Y"] = 0;
    _texture["U"] = 0;
    _texture["V"] = 0;

    glGenTextures(1, &_texture["Y"]);

    glBindTexture( GL_TEXTURE_2D, _texture["Y"]);
//    glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
//    glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// //    要注意格式图片数据格式
//    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, width(), height(), 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
//    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//    glBindTexture( GL_TEXTURE_2D, 0);

    glGenTextures(1, &_texture["U"]);
    glBindTexture( GL_TEXTURE_2D, _texture["U"]);
//    glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
//    glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, width()/2, height()/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
//    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//    glBindTexture( GL_TEXTURE_2D, 0);


    glGenTextures(1, &_texture["V"]);
    glBindTexture( GL_TEXTURE_2D, _texture["V"]);
//    glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
//    glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);//YUV渲染不能用多重贴图
//    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, width()/2, height()/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
//    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
//    glBindTexture( GL_TEXTURE_2D, 0);

    errPrint("initTexture 155");
}

void MyOpenGLRender::resizeGL(int w, int h)
{
    glViewport(0,0,w,h);
}

void MyOpenGLRender::initializeGL()
{
    initializeOpenGLFunctions();

//    _firstContext = context();
//    _mainSurface = _firstContext->surface();
//    _secondContext = new QOpenGLContext(this);
//    auto offSurface = new QOffscreenSurface(nullptr, this);
//    offSurface->setFormat(_firstContext->format());
//    offSurface->create();
//    _offSurface = offSurface;

    errPrint("initializeGL 201");

    initShaderProgrem();

    glClearColor(0, 0, 0, 1);
    glClearDepth(1);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
//    float w = width();
//    float h = height();
    //物体坐标系是左上角为（0,0）
    CCVert screen[] = {
        {-1, 1,  1,     0,0},
        {-1, -1,  1,    0,1},
        {1,  -1,  1,     1,1},
        {1,  1,  1,    1,0},
    };
    initTexture();
    glGenBuffers(1, &_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof (screen), screen, GL_STATIC_DRAW);
    _shaderprogram.bind();

    _shaderprogram.enableAttributeArray("attr_position");
    _shaderprogram.setAttributeArray("attr_position", GL_FLOAT, 0, 3, sizeof (CCVert));

    _shaderprogram.enableAttributeArray("attr_uv");
    _shaderprogram.setAttributeArray("attr_uv", GL_FLOAT, (float*)12, 2, sizeof (CCVert));

    _shaderprogram.release();

    glBindBuffer(GL_ARRAY_BUFFER, 0);

//    _firstContext->doneCurrent();
//    _secondContext->makeCurrent(_offSurface);
//    initFBO();
//    _secondContext->doneCurrent();
//    _firstContext->makeCurrent(_mainSurface);

    initPBO();
    errPrint("initializeGL 201");

}

void MyOpenGLRender::updatePBO2(std::array<GLuint, 3> pbo, std::array<GLuint, 3> pbo2, H264Frame *content)
{
    static int flag = 1;
//    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[0]);
//    glBufferData(GL_PIXEL_UNPACK_BUFFER, content->Y.length, content->Y.dataBuffer, GL_STREAM_DRAW);



//    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[1]);
//    glBufferData(GL_PIXEL_UNPACK_BUFFER, content->U.length, content->U.dataBuffer, GL_STREAM_DRAW);

//    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[2]);
//    glBufferData(GL_PIXEL_UNPACK_BUFFER, content->V.length, content->V.dataBuffer, GL_STREAM_DRAW);
//    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[0]);
    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, content->Y.length, content->Y.dataBuffer);
    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, content->Y.length, content->U.length, content->U.dataBuffer);
    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, content->Y.length + content->U.length, content->V.length, content->V.dataBuffer);
//    auto ptY1 = reinterpret_cast<unsigned char *>(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, content->Y.length + content->U.length + content->V.length + 10, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT));
//    if(ptY1)
//    {
//        memcpy(ptY1, content->Y.dataBuffer, content->Y.length);
//        memcpy(ptY1 + content->Y.length, content->U.dataBuffer, content->U.length);
//        memcpy(ptY1 + content->Y.length + content->U.length, content->V.dataBuffer, content->V.length);
//        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
//        ptY1 = nullptr;
//    }


    if(flag)
    {
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[0]);
        _shaderprogram.setUniformValue("uni_textureY", 0);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture( GL_TEXTURE_2D, _texture["Y"]);
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, content->Width, content->Height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
        errPrint("updatePBO2 274");


        _shaderprogram.setUniformValue("uni_textureU", 1);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture( GL_TEXTURE_2D, _texture["U"]);
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

//         glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, content->Width/2, content->Height/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, (char *)content->Y.length);
//        glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,0,0,content->Width/2, content->Height/2, 0);
         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,content->Width/2, content->Height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, /*ptY + */(unsigned char *)content->Y.length);
         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);


//        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[0]);
         _shaderprogram.setUniformValue("uni_textureV", 2);
         glActiveTexture(GL_TEXTURE2);
        glBindTexture( GL_TEXTURE_2D, _texture["V"]);
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, content->Width/2, content->Height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, /*ptY + */(unsigned char *)(content->Y.length + content->U.length));
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);


        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
//        glBindTexture( GL_TEXTURE_2D, 0);不能解绑，否则数据渲染会出问题，要解绑只能在调用完glDrawArrays后
    }








//    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);



    flag = 1;
    errPrint("updatePBO 274");
}



void MyOpenGLRender::updatePBO(GLuint pbo, GLuint pbo2, H264Frame *content)
{
    if(!_once)
    {
        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
        _shaderprogram.setUniformValue("uni_textureY", 0);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture( GL_TEXTURE_2D, _texture["Y"]);
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);


        glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, content->Width, content->Height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, nullptr);
//        glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, content->Width, content->Height, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);


        _shaderprogram.setUniformValue("uni_textureU", 1);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture( GL_TEXTURE_2D, _texture["U"]);
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,content->Width/2, content->Height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, /*ptY + */(unsigned char *)content->Y.length);
//        glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,
//                        content->Width/2, content->Height/2, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

        _shaderprogram.setUniformValue("uni_textureV", 2);
        glActiveTexture(GL_TEXTURE2);
        glBindTexture( GL_TEXTURE_2D, _texture["V"]);
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
//        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, content->Width/2, content->Height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, /*ptY + */(unsigned char *)(content->Y.length + content->U.length));
//        glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,
//                        content->Width/2, content->Height/2, GL_LUMINANCE, GL_UNSIGNED_BYTE
//                        , 0);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
        glDrawArrays(GL_QUADS, 0, 4);

    }



    errPrint("updatePBO 274");






//    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo2);
        auto ptY1 = reinterpret_cast<unsigned char *>(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, content->Y.length + content->U.length + content->V.length + 10, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT));
        if(ptY1)
        {
            memcpy(ptY1, content->Y.dataBuffer, content->Y.length);
            memcpy(ptY1 + content->Y.length, content->U.dataBuffer, content->U.length);
            memcpy(ptY1 + content->Y.length + content->U.length, content->V.dataBuffer, content->V.length);
            glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
            ptY1 = nullptr;
        }
    _once = false;
    errPrint("updatePBO 274");
// //    glBufferData(GL_PIXEL_UNPACK_BUFFER, content->Y.length, content->Y.dataBuffer, GL_STREAM_DRAW);
// //    if(flag < 2)
// //    {
// //        glBufferData(GL_PIXEL_UNPACK_BUFFER, content->Y.length, content->Y.dataBuffer, GL_DYNAMIC_DRAW);
// // //        auto ptr = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, content->Y.length, GL_MAP_WRITE_BIT);
// //    }else{
// //        glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, content->Y.length, content->Y.dataBuffer);
// //    }
// //    glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, content->Y.length, content->Y.dataBuffer);
//    auto ptr = reinterpret_cast<unsigned char*>(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, content->Y.length, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT));
//    if(ptr)
//    {
//        memcpy(ptr, content->Y.dataBuffer, content->Y.length);
//        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
//        ptr = nullptr;
//    }else{
//        qDebug() << "ptr glMapBufferRange err !";
//    }
//    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

//    errPrint("updatePBO 274");

//    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[1]);
// //    glBufferData(GL_PIXEL_UNPACK_BUFFER, content->U.length, content->U.dataBuffer, GL_STREAM_DRAW);
// //    if(flag < 2)
// //    {
// //        glBufferData(GL_PIXEL_UNPACK_BUFFER, content->U.length * 1.5, 0, GL_DYNAMIC_DRAW);
// //        glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, content->U.length, content->U.dataBuffer);
// // //        auto ptrU = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, content->U.length, GL_MAP_WRITE_BIT);

// //    }else{
// //        glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, content->U.length, content->U.dataBuffer);
// //    }
//        errPrint("updatePBO 274");
//    auto ptrU = reinterpret_cast<unsigned char*>(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, content->U.length, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT));
//        if(ptrU)
//        {
//            memcpy(ptrU, content->U.dataBuffer, content->U.length);
//            glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
//            ptrU = nullptr;
//        }else{
//            qDebug() << "ptrU glMapBufferRange err !";
//        }
//    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);



//    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo[2]);
// //    glBufferData(GL_PIXEL_UNPACK_BUFFER, content->V.length, content->V.dataBuffer, GL_STREAM_DRAW);
// //    if(flag < 2)
// //    {
// //        glBufferData(GL_PIXEL_UNPACK_BUFFER, content->V.length * 1.5, 0, GL_DYNAMIC_DRAW);
// //        glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, content->V.length, content->V.dataBuffer);
// //        ++flag;
// // //        flag = true;
// // //        auto ptrV = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, content->U.length, GL_MAP_WRITE_BIT);
// //    }else{
// //        glBufferSubData(GL_PIXEL_UNPACK_BUFFER, 0, content->V.length, content->V.dataBuffer);
// //    }
//    auto ptrV = reinterpret_cast<unsigned char*>(glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, content->V.length, GL_MAP_WRITE_BIT|GL_MAP_INVALIDATE_BUFFER_BIT));
//    if(ptrV)
//    {
//        memcpy(ptrV, content->V.dataBuffer, content->V.length);
//        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
//        ptrV = nullptr;
//    }else{
//        qDebug() << "ptrU glMapBufferRange err !";
//    }
//    glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
//    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

}

void MyOpenGLRender::renderContent3(H264Frame* content)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindBuffer(GL_ARRAY_BUFFER, _vbo);

    QMatrix4x4 mart;
    mart.setToIdentity();
    mart.ortho(-1, 1, -1, 1, 0.1, 1000);
//    mart.rotate(-90, 0, 0, 1);
    mart.translate(0, 0, -3);
    auto shade = StartShader(_shaderprogram);
//    _shaderprogram.setUniformValue("fbo_flag", true);
    _shaderprogram.setUniformValue("uni_mat", mart);

    _shaderprogram.setUniformValue("uni_textureY", 0);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture( GL_TEXTURE_2D, _texture["Y"]);
    glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);//如果是更新所有数据，最好用glTexImage2D，glTexSubImage2D容易出现绿条带。
    glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, content->Width, content->Height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, content->Y.dataBuffer);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);



   _shaderprogram.setUniformValue("uni_textureU", 1);

   glActiveTexture(GL_TEXTURE1);
   glBindTexture( GL_TEXTURE_2D, _texture["U"]);
   glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, content->Width/2, content->Height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, content->U.dataBuffer);

   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);



   _shaderprogram.setUniformValue("uni_textureV", 2);
   glActiveTexture(GL_TEXTURE2);
   glBindTexture( GL_TEXTURE_2D, _texture["V"]);
   glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, content->Width/2, content->Height/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, content->V.dataBuffer);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);

//   glBindTexture(GL_TEXTURE_2D, 0);
   glDrawArrays(GL_QUADS, 0, 4);
//   glBindTexture(GL_TEXTURE_2D, 0);
}


void MyOpenGLRender::renderContent2(H264Frame* content)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();



    static CCVert triangleVert[] = {
        {-1, 1,  1,     0,0},
        {-1, -1,  1,    0,1},
        {1,  1,  1,     1,0},
        {1,  -1,  1,    1,1},
    };

    QMatrix4x4 matrix;
    matrix.ortho(-1,1,-1,1,0.1,1000);
    matrix.translate(0,0,-3);


    _shaderprogram.bind();

    _shaderprogram.setUniformValue("uni_mat",matrix);


    _shaderprogram.enableAttributeArray("attr_position");
    _shaderprogram.enableAttributeArray("attr_uv");

    _shaderprogram.setAttributeArray("attr_position",GL_FLOAT,triangleVert,3,sizeof(CCVert));
    _shaderprogram.setAttributeArray("attr_uv",GL_FLOAT,&triangleVert[0].u,2,sizeof(CCVert));


    auto m_nVideoW = content->Width;
    auto m_nVideoH = content->Height;

   _shaderprogram.setUniformValue("uni_textureY",0);
   glActiveTexture(GL_TEXTURE0);
   glBindTexture( GL_TEXTURE_2D, _texture["Y"]);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, content->Width, content->Height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, content->Y.dataBuffer);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
   glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

   _shaderprogram.setUniformValue("uni_textureU",1);
   glActiveTexture(GL_TEXTURE1);
   glBindTexture( GL_TEXTURE_2D, _texture["U"]);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE,m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, content->U.dataBuffer);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
   glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

   _shaderprogram.setUniformValue("uni_textureV",2);
   glActiveTexture(GL_TEXTURE2);
   glBindTexture( GL_TEXTURE_2D, _texture["V"]);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
   glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, m_nVideoW/2, m_nVideoH/2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, content->V.dataBuffer);
   glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
   glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

   glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);


   _shaderprogram.disableAttributeArray("attr_position");
   _shaderprogram.disableAttributeArray("attr_uv");

   _shaderprogram.release();
}



void MyOpenGLRender::renderContent(H264Frame* content)
{
    static uint64_t index = 0;

    glClearColor( 0, 0, 0, 1 );
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);



    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    QMatrix4x4 mart;
    mart.setToIdentity();
    mart.ortho(-1, 1, -1, 1, 0.1, 1000);

    mart.translate(0, 0, -3);
    auto shade = StartShader(_shaderprogram);
    _shaderprogram.setUniformValue("uni_mat", mart);


//    updatePBO2({_pboArry[0],_pboArry[1], _pboArry[2]}, {_pboArry[3],_pboArry[4], _pboArry[5]}, content);
    ++index;
    if(index % 2)
    {
        updatePBO(_pboArry[0], _pboArry[1], content);
    }else{
        updatePBO(_pboArry[1], _pboArry[0], content);
        index = 0;
    }
    errPrint("render 311");


    errPrint("render 311");

    glBindBuffer(GL_ARRAY_BUFFER, 0);

}

//这个函数在解码线程中用到，与paintGL函数是不同的线程，update只是触发这个函数，执行是在界面线程，所以有数据同步问题，即_renderContent被覆盖的时候，
//可能数据还未完全提交给纹理对象（GPU），所以加锁。
void MyOpenGLRender::render(std::unique_ptr<H264Frame> content)
{
    if(content == nullptr)
    {
        return;
    }
    {
        std::unique_lock<std::mutex> lock(_renderMutex);
        _renderContent = std::move(content);
    }

    update();

}

void MyOpenGLRender::paintGL()
{
    if(SingleInstance::GetInstanca().StartFlag)
    {
        std::unique_lock<std::mutex> lock(_renderMutex);
        renderContent(_renderContent.get());
//        _firstContext->makeCurrent(_mainSurface);
//        glBindBuffer(GL_ARRAY_BUFFER, _vbo);
//        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//        QMatrix4x4 mart;
//        mart.setToIdentity();
//        mart.ortho(-1, 1, -1, 1, -100, 100);
//        mart.translate(0, 0, -3);
//        auto shade = StartShader(_shaderprogram);
//        _shaderprogram.setUniformValue("fbo_flag", false);
//        _shaderprogram.setUniformValue("uni_mat", mart);

//        auto posArry = Attritute("attr_position", _shaderprogram);
//        _shaderprogram.setAttributeArray("attr_position", 0, 3, sizeof (CCVert));

//        auto uvArry = Attritute("attr_uv", _shaderprogram);
//        _shaderprogram.setAttributeArray("attr_uv", (float*)12, 2, sizeof (CCVert));


//        glActiveTexture(GL_TEXTURE3);
//        glBindTexture( GL_TEXTURE_2D, _fboTexture);
//        _shaderprogram.setUniformValue("uni_textureRgb", 3);
//        glDrawArrays(GL_QUADS, 0, 4);
//        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
}
